#pragma once

#include <glad/glad.h>
#include <string>
#include <ostream>
#include <iostream>
#include <fstream>
#include <sstream>

extern std::string realPath;

static std::string getProgramDir(){
    if(realPath.empty()){
        char exeFullPath[MAX_PATH]; // Full path
        std::string strPath = "";
        GetModuleFileName(NULL,exeFullPath,MAX_PATH);
        strPath=(std::string)exeFullPath;    // Get full path of the file
        int pos = strPath.find_last_of('\\', strPath.length());
        realPath = strPath.substr(0, pos);  // Return the directory without the file name
        std::cout << "set default assest path : " << realPath << std::endl;
    }
    return realPath + "";
}

static void setRealPath(std::string path){
    std::cout << "set assest path : " << path << std::endl;
    realPath = path;
}

static char* readFilePath(const char* p){
    std::string basedir = getProgramDir() + "/";
    const char* str = basedir.data();
	const size_t len = strlen(str) + strlen(p);
    char *n_str = new char[len+1];
    strcpy(n_str, str);
    strcat(n_str, p);
    return n_str;
}

static void readBytesFromFile(const char* path, std::vector<char> & buffer) {
	std::ifstream file;
	file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	const char* realpath = readFilePath(path);
	try
	{
		file.open(realpath, std::ios_base::binary);
		std::vector<char> bytes(
			(std::istreambuf_iterator<char>(file)),
			(std::istreambuf_iterator<char>()));
		buffer.insert(std::end(buffer), std::begin(bytes), std::end(bytes));
		file.close();
	}
	catch (std::ifstream::failure & e)
	{
		std::cout << "ERROR::FILE_NOT_SUCCESSFULLY_READ : " << realpath  << "  |  " << e.what() << std::endl;
		exit(1);
	}
}

static std::string readStringFromFile(const char* path) {
	std::string content;
	std::ifstream file;
	file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    const char* realpath = readFilePath(path);
	try
	{
		file.open(realpath);
		std::stringstream stream;
		stream << file.rdbuf();
		file.close();
		content = stream.str();
	}
	catch (std::ifstream::failure & e)
	{
		std::cout << "ERROR::FILE_NOT_SUCCESSFULLY_READ STRING : " << realpath << "  |  " << e.what() << std::endl;
		exit(1);
	}
	return content;
}

static bool replace(std::string& str, const std::string& from, const std::string& to) {
	size_t start_pos = str.find(from);
	if (start_pos == std::string::npos)
		return false;
	str.replace(start_pos, from.length(), to);
	return true;
}

static void checkGlErrors(std::string desc)
{
	GLenum e = glGetError();
	if (e != GL_NO_ERROR) {
		fprintf(stderr, "OpenGL error in \"%s\": (%d)\n", desc.c_str(), e); //todo error must be here
		exit(20);
	}
}
